// automatically generated code
// (c) 2010, Pierre Bayerl
// 
// FloatIndexedSubMatrix.scala
// +--------------------------------
// | classname: FloatMatrix
// | inner type: Float
// +--------------------------------
//
// time of creation: Thu Mar 25 20:07:25 CET 2010
//
package org.pi.common.matrix


final class FloatIndexedSubMatrix(val indexSource: IntMatrix, val dataSource: FloatMatrix) extends Matrix[Float]
{
	val multidimIndices = indexSource.multidimIndices

	final def shape = indexSource.shape
	final def length = indexSource.length
	final def length(dim: Int) = indexSource.length(dim)

	// ===============================
	// element-wise apply/update
	// ===============================

	@inline
	final override def apply(d1: Int) : Float = dataSource(indexSource(d1))
	@inline
	final override def apply(d1: Int, d2: Int) : Float = dataSource(indexSource(d1,d2))
	@inline
	final override def apply(d1: Int, d2: Int, d3: Int) : Float = dataSource(indexSource(d1,d2,d3))

	@inline
	final override def update(d1: Int, value: Float) = { dataSource(indexSource(d1)) = value }
	@inline
	final override def update(d1: Int, d2: Int, value: Float) = { dataSource(indexSource(d1,d2)) = value }
	@inline
	final override def update(d1: Int, d2: Int, d3: Int, value: Float) = { dataSource(indexSource(d1,d2,d3)) = value }


	// ===============================
	// misc stuff
	// ===============================

	final def reshape(dims: Int*) = {
		val result = FloatMatrix(dims :_* )
		result.copyValuesFrom(this)
		result
	}

	/** set all entries to the same value */
	final def setAllValues(value: Float): Unit = {
		var index = 0;
		val n = length
		while(index<n) { 
			update(index, value)
			index += 1
		}
	}

	def trans() : FloatMatrix = {
		if (multidimIndices.dimCount == 1) {
			val result = new FloatMatrix(1,length)
			result.copyValuesFrom(this)
			result
		}
		else if (multidimIndices.dimCount == 2) {
			val result = new FloatMatrix(length(1),length(0))
			var inIndex1 = 0
			var inIndex2 = 0
			val n1 = length(0)
			val n2 = length(1)
			while (inIndex1 < n1) {
				while (inIndex2 < n2) {
					result(inIndex2, inIndex1) = apply(inIndex1, inIndex2)
					inIndex2 += 1
				}
				inIndex1+=1
			}
			result
		}
		else {
			throw new Error("transpose only defined for 1d and 2d")
		}
	}

	/** checks if another matrix has the same size */
	final def hasSameShape(indices: org.pi.common.matrix.indices.MultidimensionalIndices) : Boolean = multidimIndices.equals(indices)

	// ===============================
	// copy and convert methods
	// ===============================


	// convert matrix: Float to Boolean (copy FloatMatrix -> BooleanMatrix):
	final def toBooleanMatrix() : BooleanMatrix = {
		val result: BooleanMatrix = new BooleanMatrix(shape :_* );
		copyTo( result )
		result
	}

	// convert matrix: Float to Int (copy FloatMatrix -> IntMatrix):
	final def toIntMatrix() : IntMatrix = {
		val result: IntMatrix = new IntMatrix(shape :_* );
		copyTo( result )
		result
	}


	/** copy the values to another matrix. The other matrix must have the same size as this matrix */
	final def copyTo(destination: FloatMatrix): Unit = {
		//TODO checksize instead of ...destination.resize( size :_* )
		if (!destination.hasSameShape(this)) throw new Error("shape must match!")
		copyValuesTo(destination)
	}
	/** copy the values to another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesTo(destination: FloatMatrix): Unit = {
		if (destination.length != length) throw new Error("length must match!")
		var index = 0
		val n = length
		while(index<n) { 

			destination(index) = apply(index)

			index += 1
		}
	}

	/** copy the values from another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesFrom(source: FloatMatrix) : Unit = {
		source.copyValuesTo(this)
	}
	/** copy the values from another matrix. The other matrix must have the same size as this matrix */
	final def copyFrom(source: FloatMatrix) : Unit = {
		source.copyTo(this)
	}

	/** checks if another matrix has the same size */
	final def hasSameShape(otherMatrix: FloatMatrix) : Boolean = otherMatrix.hasSameShape(multidimIndices)


	/** copy the values to another matrix. The other matrix must have the same size as this matrix */
	final def copyTo(destination: IntMatrix): Unit = {
		//TODO checksize instead of ...destination.resize( size :_* )
		if (!destination.hasSameShape(this)) throw new Error("shape must match!")
		copyValuesTo(destination)
	}
	/** copy the values to another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesTo(destination: IntMatrix): Unit = {
		if (destination.length != length) throw new Error("length must match!")
		var index = 0
		val n = length
		while(index<n) { 


			destination(index) = apply(index).toInt


			index += 1
		}
	}

	/** copy the values from another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesFrom(source: IntMatrix) : Unit = {
		source.copyValuesTo(this)
	}
	/** copy the values from another matrix. The other matrix must have the same size as this matrix */
	final def copyFrom(source: IntMatrix) : Unit = {
		source.copyTo(this)
	}

	/** checks if another matrix has the same size */
	final def hasSameShape(otherMatrix: IntMatrix) : Boolean = otherMatrix.hasSameShape(multidimIndices)


	/** copy the values to another matrix. The other matrix must have the same size as this matrix */
	final def copyTo(destination: BooleanMatrix): Unit = {
		//TODO checksize instead of ...destination.resize( size :_* )
		if (!destination.hasSameShape(this)) throw new Error("shape must match!")
		copyValuesTo(destination)
	}
	/** copy the values to another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesTo(destination: BooleanMatrix): Unit = {
		if (destination.length != length) throw new Error("length must match!")
		var index = 0
		val n = length
		while(index<n) { 


			if (apply(index)==0) destination(index) = false
			else destination(index) = true


			index += 1
		}
	}

	/** copy the values from another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesFrom(source: BooleanMatrix) : Unit = {
		source.copyValuesTo(this)
	}
	/** copy the values from another matrix. The other matrix must have the same size as this matrix */
	final def copyFrom(source: BooleanMatrix) : Unit = {
		source.copyTo(this)
	}

	/** checks if another matrix has the same size */
	final def hasSameShape(otherMatrix: BooleanMatrix) : Boolean = otherMatrix.hasSameShape(multidimIndices)


	/** copy the values to another matrix. The other matrix must have the same size as this matrix */
	final def copyTo(destination: FloatIndexedSubMatrix): Unit = {
		//TODO checksize instead of ...destination.resize( size :_* )
		if (!destination.hasSameShape(this)) throw new Error("shape must match!")
		copyValuesTo(destination)
	}
	/** copy the values to another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesTo(destination: FloatIndexedSubMatrix): Unit = {
		if (destination.length != length) throw new Error("length must match!")
		var index = 0
		val n = length
		while(index<n) { 

			destination(index) = apply(index)

			index += 1
		}
	}

	/** copy the values from another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesFrom(source: FloatIndexedSubMatrix) : Unit = {
		source.copyValuesTo(this)
	}
	/** copy the values from another matrix. The other matrix must have the same size as this matrix */
	final def copyFrom(source: FloatIndexedSubMatrix) : Unit = {
		source.copyTo(this)
	}

	/** checks if another matrix has the same size */
	final def hasSameShape(otherMatrix: FloatIndexedSubMatrix) : Boolean = otherMatrix.hasSameShape(multidimIndices)


	/** copy the values to another matrix. The other matrix must have the same size as this matrix */
	final def copyTo(destination: IntIndexedSubMatrix): Unit = {
		//TODO checksize instead of ...destination.resize( size :_* )
		if (!destination.hasSameShape(this)) throw new Error("shape must match!")
		copyValuesTo(destination)
	}
	/** copy the values to another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesTo(destination: IntIndexedSubMatrix): Unit = {
		if (destination.length != length) throw new Error("length must match!")
		var index = 0
		val n = length
		while(index<n) { 


			destination(index) = apply(index).toInt


			index += 1
		}
	}

	/** copy the values from another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesFrom(source: IntIndexedSubMatrix) : Unit = {
		source.copyValuesTo(this)
	}
	/** copy the values from another matrix. The other matrix must have the same size as this matrix */
	final def copyFrom(source: IntIndexedSubMatrix) : Unit = {
		source.copyTo(this)
	}

	/** checks if another matrix has the same size */
	final def hasSameShape(otherMatrix: IntIndexedSubMatrix) : Boolean = otherMatrix.hasSameShape(multidimIndices)


	/** copy the values to another matrix. The other matrix must have the same size as this matrix */
	final def copyTo(destination: BooleanIndexedSubMatrix): Unit = {
		//TODO checksize instead of ...destination.resize( size :_* )
		if (!destination.hasSameShape(this)) throw new Error("shape must match!")
		copyValuesTo(destination)
	}
	/** copy the values to another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesTo(destination: BooleanIndexedSubMatrix): Unit = {
		if (destination.length != length) throw new Error("length must match!")
		var index = 0
		val n = length
		while(index<n) { 


			if (apply(index)==0) destination(index) = false
			else destination(index) = true


			index += 1
		}
	}

	/** copy the values from another matrix. The other matrix must have the same number of elements as this matrix */
	final def copyValuesFrom(source: BooleanIndexedSubMatrix) : Unit = {
		source.copyValuesTo(this)
	}
	/** copy the values from another matrix. The other matrix must have the same size as this matrix */
	final def copyFrom(source: BooleanIndexedSubMatrix) : Unit = {
		source.copyTo(this)
	}

	/** checks if another matrix has the same size */
	final def hasSameShape(otherMatrix: BooleanIndexedSubMatrix) : Boolean = otherMatrix.hasSameShape(multidimIndices)



	/** copy the current matrix */
	def copy() : FloatMatrix = {
		val result: FloatMatrix = new FloatMatrix(shape :_*);
		copyTo( result )
		result
	}

	// ===============================
	// create submatrices
	// ===============================

	/** get a submatrix which referneces the same memory as
	the original matrix. 
	@param indices indicates a matrix with the zero-based indices from the original matrix to be used as output.
	@return a matrix of the same size of the indices matrix. 
	*/
	final def getReferenceMatrix(indices: IntSelection) : FloatIndexedSubMatrix = FloatIndexedSubMatrix(indices.toIntMatrixForGivenStartEndIndices(0,length),this)

	/** get a submatrix which referneces the same memory as
	the original matrix. 
	@param flags indicates the locations of value sin the input matrix to be used 
	(the size of flags mustr match the siz eof this matrix.
	@return a 1D-matrix with sum(flags) elements. 
	*/
	final def getReferenceMatrix(flags: BooleanMatrix) : FloatIndexedSubMatrix = FloatIndexedSubMatrix(flags,this)

	/** get a submatrix which referneces the same memory as
	the original matrix. 
	@param indices1 indicates the rows to be used.
	@param indices2 indicates the columns to be used.
	@return a matrix of the size indices1.length x indices2.length. 
	*/
	final def getReferenceMatrix(indices1: IntSelection, indices2: IntSelection) : FloatIndexedSubMatrix = FloatIndexedSubMatrix(indices1.toIntMatrixForGivenStartEndIndices(0,length(0)), indices2.toIntMatrixForGivenStartEndIndices(0,length(1)), this)

	/** get a submatrix which referneces the same memory as
	the original matrix. 
	@param indices1 indicates the planes to be used.
	@param indices2 indicates the rows to be used.
	@param indices3 indicates the columns to be used.
	@return a matrix of the size indices1.length x indices2.length x indices3.length. 
	*/
	final def getReferenceMatrix(indices1: IntSelection, indices2: IntSelection, indices3: IntSelection) : FloatIndexedSubMatrix = FloatIndexedSubMatrix(indices1.toIntMatrixForGivenStartEndIndices(0,length(0)), indices2.toIntMatrixForGivenStartEndIndices(0,length(1)), indices3.toIntMatrixForGivenStartEndIndices(0,length(2)), this)

	// ===============================
	// apply/update for submatrices (IndexedSubMatrices)
	// ===============================

	/** returns a submatrix. is mapped to getReferenceMatrix. */
	final def apply(indices: IntSelection) : FloatIndexedSubMatrix = getReferenceMatrix(indices)
	/** returns a submatrix. is mapped to getReferenceMatrix. */
	def apply(flags: BooleanMatrix) : FloatIndexedSubMatrix = getReferenceMatrix(flags)
	/** returns a submatrix. is mapped to getReferenceMatrix. */
	final def apply(indices1: IntSelection, indices2: IntSelection) : FloatIndexedSubMatrix = getReferenceMatrix(indices1, indices2)
	/** returns a submatrix. is mapped to getReferenceMatrix. */
	final def apply(indices1: IntSelection, indices2: IntSelection, indices3: IntSelection) : FloatIndexedSubMatrix = getReferenceMatrix(indices1, indices2, indices3)

	/** set parts of the values */
	final def update(indices: IntSelection, values: FloatMatrix) : Unit = getReferenceMatrix(indices).copyFrom(values)
	/** set parts of the values */
	final def update(flags: BooleanMatrix, values: FloatMatrix) : Unit = getReferenceMatrix(flags).copyFrom(values)
	/** set parts of the values */
	final def update(indices1: IntSelection, indices2: IntSelection, values: FloatMatrix) : Unit = getReferenceMatrix(indices1, indices2).copyFrom(values)
	/** set parts of the values */
	final def update(indices1: IntSelection, indices2: IntSelection, indices3: IntSelection, values: FloatMatrix) : Unit = getReferenceMatrix(indices1, indices2, indices3).copyFrom(values)

	/** set parts of the values */
	final def update(indices: IntSelection, value: Float) : Unit = getReferenceMatrix(indices).setAllValues(value)
	/** set parts of the values */
	final def update(flags: BooleanMatrix, value: Float) : Unit = getReferenceMatrix(flags).setAllValues(value)
	/** set parts of the values */
	final def update(indices1: IntSelection, indices2: IntSelection, value: Float) : Unit = getReferenceMatrix(indices1, indices2).setAllValues(value)
	/** set parts of the values */
	final def update(indices1: IntSelection, indices2: IntSelection, indices3: IntSelection, value: Float) : Unit = getReferenceMatrix(indices1, indices2, indices3).setAllValues(value)

	// ===============================
	// apply/update for submatrices (RangedSubMatrices)
	// ===============================

	// TODO range!

	// ===============================
	// ElementWiseOps
	// ===============================



	/** operator + (mapped to method +)
	@return a FloatMatrix */
	final def +(m : FloatMatrix) : FloatMatrix = {
		if (!hasSameShape(m)) throw new Error("size of matrices must match")
		var result = new FloatMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) + m(index))
			index += 1
		}
		result
	}
	/** operator + (mapped to method +)
	@return a FloatMatrix */
	final def +(value : Float) : FloatMatrix = {
		var result = new FloatMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) + value)
			index += 1
		}
		result
	}


	/** operator - (mapped to method -)
	@return a FloatMatrix */
	final def -(m : FloatMatrix) : FloatMatrix = {
		if (!hasSameShape(m)) throw new Error("size of matrices must match")
		var result = new FloatMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) - m(index))
			index += 1
		}
		result
	}
	/** operator - (mapped to method -)
	@return a FloatMatrix */
	final def -(value : Float) : FloatMatrix = {
		var result = new FloatMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) - value)
			index += 1
		}
		result
	}


	/** operator / (mapped to method /)
	@return a FloatMatrix */
	final def /(m : FloatMatrix) : FloatMatrix = {
		if (!hasSameShape(m)) throw new Error("size of matrices must match")
		var result = new FloatMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) / m(index))
			index += 1
		}
		result
	}
	/** operator / (mapped to method /)
	@return a FloatMatrix */
	final def /(value : Float) : FloatMatrix = {
		var result = new FloatMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) / value)
			index += 1
		}
		result
	}


	/** operator * (mapped to method *)
	@return a FloatMatrix */
	final def *(m : FloatMatrix) : FloatMatrix = {
		if (!hasSameShape(m)) throw new Error("size of matrices must match")
		var result = new FloatMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) * m(index))
			index += 1
		}
		result
	}
	/** operator * (mapped to method *)
	@return a FloatMatrix */
	final def *(value : Float) : FloatMatrix = {
		var result = new FloatMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) * value)
			index += 1
		}
		result
	}


	/** operator < (mapped to method <)
	@return a BooleanMatrix */
	final def <(m : FloatMatrix) : BooleanMatrix = {
		if (!hasSameShape(m)) throw new Error("size of matrices must match")
		var result = new BooleanMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) < m(index))
			index += 1
		}
		result
	}
	/** operator < (mapped to method <)
	@return a BooleanMatrix */
	final def <(value : Float) : BooleanMatrix = {
		var result = new BooleanMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) < value)
			index += 1
		}
		result
	}


	/** operator > (mapped to method >)
	@return a BooleanMatrix */
	final def >(m : FloatMatrix) : BooleanMatrix = {
		if (!hasSameShape(m)) throw new Error("size of matrices must match")
		var result = new BooleanMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) > m(index))
			index += 1
		}
		result
	}
	/** operator > (mapped to method >)
	@return a BooleanMatrix */
	final def >(value : Float) : BooleanMatrix = {
		var result = new BooleanMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) > value)
			index += 1
		}
		result
	}


	/** operator <= (mapped to method <=)
	@return a BooleanMatrix */
	final def <=(m : FloatMatrix) : BooleanMatrix = {
		if (!hasSameShape(m)) throw new Error("size of matrices must match")
		var result = new BooleanMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) <= m(index))
			index += 1
		}
		result
	}
	/** operator <= (mapped to method <=)
	@return a BooleanMatrix */
	final def <=(value : Float) : BooleanMatrix = {
		var result = new BooleanMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) <= value)
			index += 1
		}
		result
	}


	/** operator >= (mapped to method >=)
	@return a BooleanMatrix */
	final def >=(m : FloatMatrix) : BooleanMatrix = {
		if (!hasSameShape(m)) throw new Error("size of matrices must match")
		var result = new BooleanMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) >= m(index))
			index += 1
		}
		result
	}
	/** operator >= (mapped to method >=)
	@return a BooleanMatrix */
	final def >=(value : Float) : BooleanMatrix = {
		var result = new BooleanMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) >= value)
			index += 1
		}
		result
	}


	/** operator == (mapped to method elementWiseEquals)
	@return a BooleanMatrix */
	final def elementWiseEquals(m : FloatMatrix) : BooleanMatrix = {
		if (!hasSameShape(m)) throw new Error("size of matrices must match")
		var result = new BooleanMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) == m(index))
			index += 1
		}
		result
	}
	/** operator == (mapped to method elementWiseEquals)
	@return a BooleanMatrix */
	final def elementWiseEquals(value : Float) : BooleanMatrix = {
		var result = new BooleanMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (apply(index) == value)
			index += 1
		}
		result
	}




	/** operator - (mapped to method unary_-)
	@return a FloatMatrix */
	final def unary_- : FloatMatrix = {
		var result = new FloatMatrix( shape :_* )
		var index: Int = 0
		val n = length
		while (index < n) {
			result(index) = (- apply(index))
			index += 1
		}
		result
	}


	override def toString() = {
		var text = multidimIndices.dimCount match {
			case 1 => "FloatMatrix(" + multidimIndices.size(0)
			case 2 => "FloatMatrix(" + multidimIndices.size(0) + " x " + multidimIndices.size(1) 
			case 3 => "FloatMatrix(" + multidimIndices.size(0) + " x " + multidimIndices.size(1) + " x " + multidimIndices.size(2)
			case _ => throw new Exception("unknown dimension")
		}
		text += ")=[ "
		for (i <- 0 until this.length) {
			if (multidimIndices.dimCount>1 && i%multidimIndices.size(0)==multidimIndices.size(0)-1) text += (this(i)+";\n")
			else text += (this(i)+" ")
		}
		text += "]"
		text
	}  
}


/** companion object */
object FloatIndexedSubMatrix {
	// ===============================
	// additional builders
	// ===============================

	def apply(newIndices: IntMatrix, source: FloatMatrix) = {
		new FloatIndexedSubMatrix(newIndices,source)
	}

	def apply(flags: BooleanMatrix, source: FloatMatrix) = {
		val n = flags.foldLeft(0){ (sum,value) => if (value) sum+1 else sum }
		val newIndices = new IntMatrix(n)
		var index0 = 0
		var index = 0
		val m = flags.length
		while(index0<m) {
			if(flags(index0)) {
				newIndices(index) = index0
				index += 1
			}
			index0 += 1
		}
		new FloatIndexedSubMatrix(newIndices,source)
	}

	def apply(indices1: IntMatrix, indices2: IntMatrix, source: FloatMatrix) = {
		val n1 = indices1.length;
		val n2 = indices2.length;
		val newIndices = new IntMatrix(n1,n2)
		var index2 = 0
		var index = 0
		while(index2<n2) {
			var index1 = 0
			while(index1<n1) {
				newIndices(index) = source.multidimIndices(indices1(index1), indices2(index2));
				index += 1
				index1 += 1
			}
			index2 += 1
		}
		new FloatIndexedSubMatrix(newIndices,source)
	}

	def apply(indices1: IntMatrix, indices2: IntMatrix, indices3: IntMatrix, source: FloatMatrix) = {
		val n1 = indices1.length;
		val n2 = indices2.length;
		val n3 = indices3.length;
		val newIndices = new IntMatrix(n1,n2,n3)
		var index3 = 0
		var index = 0
		while(index3<n3) {
			var index2 = 0
			while(index2<n2) {
				var index1 = 0
				while(index1<n1) {
					newIndices(index) = source.multidimIndices(indices1(index1), indices2(index2), indices3(index3));
					index += 1
					index1 += 1
				}
				index2 += 1
			}
			index3 += 1
		}
		new FloatIndexedSubMatrix(newIndices,source)
	}

	def apply(newIndicesParam: IntMatrix, source: FloatIndexedSubMatrix) = {
		val newIndices = new IntMatrix(newIndicesParam.shape :_*)
		var index = 0
		val n = newIndices.length
		while (index<n) {
			newIndices(index) = source.indexSource(newIndicesParam(index))
			index+=1
		}
		new FloatIndexedSubMatrix(newIndices,source.dataSource)
	}

	def apply(flags: BooleanMatrix, source: FloatIndexedSubMatrix) = {
		val n = flags.foldLeft(0){ (sum,value) => if (value) sum+1 else sum }
		val newIndices = new IntMatrix(n)
		var index0 = 0
		var index = 0
		val m = flags.length
		while(index0<m) {
			if(flags(index0)) {
				newIndices(index) = source.indexSource(index0)
				index += 1
			}
			index0 += 1
		}
		new FloatIndexedSubMatrix(newIndices,source.dataSource)
	}

	def apply(indices1: IntMatrix, indices2: IntMatrix, source: FloatIndexedSubMatrix) = {
		val n1 = indices1.length;
		val n2 = indices2.length;
		val newIndices = new IntMatrix(n1,n2)
		var index2 = 0
		var index = 0
		while(index2<n2) {
			var index1 = 0
			while(index1<n1) {
				newIndices(index) = source.indexSource(source.multidimIndices(indices1(index1), indices2(index2)));
				index += 1
				index1 += 1
			}
			index2 += 1
		}
		new FloatIndexedSubMatrix(newIndices,source.dataSource)
	}

	def apply(indices1: IntMatrix, indices2: IntMatrix, indices3: IntMatrix, source: FloatIndexedSubMatrix) = {
		val n1 = indices1.length;
		val n2 = indices2.length;
		val n3 = indices3.length;
		val newIndices = new IntMatrix(n1,n2,n3)
		var index3 = 0
		var index = 0
		while(index3<n3) {
			var index2 = 0
			while(index2<n2) {
				var index1 = 0
				while(index1<n1) {
					newIndices(index) = source.indexSource(source.multidimIndices(indices1(index1), indices2(index2), indices3(index3)));
					index += 1
					index1 += 1
				}
				index2 += 1
			}
			index3 += 1
		}
		new FloatIndexedSubMatrix(newIndices,source.dataSource)
	}

}

